//
//  lua_custom_manual.cpp
//  client
//
//  Created by DuanHongbo on 15/1/29.
//
//

#include "lua_custom_manual.h"
#include "custom.h"
#include "tolua_fix.h"
#include "LuaBasicConversions.h"
#include "custom/Utils.h"
#include "CCLuaValue.h"
#include "CCLuaEngine.h"
#include "base/CCConfiguration.h"

int lua_custom_BezierByForward_create(lua_State* tolua_S)
{
    int argc = 0;
    bool ok  = true;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif
    
#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertable(tolua_S,1,"BezierByForward",0,&tolua_err)) goto tolua_lerror;
#endif
    
    argc = lua_gettop(tolua_S) - 1;
    
    if (argc == 4)
    {
        double arg0;
        cocos2d::_ccBezierConfig arg1;
        bool arg2;
        double arg3;
        ok &= luaval_to_number(tolua_S, 2,&arg0, "BezierByForward:create");

        int num = 0;
        cocos2d::Vec2 *arr = NULL;
        ok &= luaval_to_array_of_vec2(tolua_S, 3, &arr, &num, "cc.BezierBy:create");
        if (!ok)
            return 0;
        
        if (num < 3)
        {
            CC_SAFE_DELETE_ARRAY(arr);
            return 0;
        }
        
        arg1.controlPoint_1 = arr[0];
        arg1.controlPoint_2 = arr[1];
        arg1.endPosition = arr[2];
        CC_SAFE_DELETE_ARRAY(arr);

        ok &= luaval_to_boolean(tolua_S, 4,&arg2, "BezierByForward:create");
        ok &= luaval_to_number(tolua_S, 5,&arg3, "BezierByForward:create");
        if(!ok)
        {
            tolua_error(tolua_S,"invalid arguments in function 'lua_custom_BezierByForward_create'", nullptr);
            return 0;
        }
        BezierByForward* ret = BezierByForward::create(arg0, arg1, arg2, arg3);
        object_to_luaval<BezierByForward>(tolua_S, "BezierByForward",(BezierByForward*)ret);
        return 1;
    }
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "BezierByForward:create",argc, 2);
    return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'lua_custom_BezierByForward_create'.",&tolua_err);
#endif
    return 0;
}


int lua_custom_BezierToForward_create(lua_State* tolua_S)
{
    int argc = 0;
    bool ok  = true;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
#endif
    
#if COCOS2D_DEBUG >= 1
    if (!tolua_isusertable(tolua_S,1,"BezierToForward",0,&tolua_err)) goto tolua_lerror;
#endif
    
    argc = lua_gettop(tolua_S) - 1;

    if (argc == 4)
    {
        double arg0;
        cocos2d::_ccBezierConfig arg1;
        bool arg2;
        double arg3;
        ok &= luaval_to_number(tolua_S, 2,&arg0, "BezierToForward:create");
        
        int num = 0;
        cocos2d::Vec2 *arr = NULL;
        ok &= luaval_to_array_of_vec2(tolua_S, 3, &arr, &num, "cc.BezierBy:create");
        if (!ok)
            return 0;
        
        if (num < 3)
        {
            CC_SAFE_DELETE_ARRAY(arr);
            return 0;
        }
        
        arg1.controlPoint_1 = arr[0];
        arg1.controlPoint_2 = arr[1];
        arg1.endPosition = arr[2];
        CC_SAFE_DELETE_ARRAY(arr);
        ok &= luaval_to_boolean(tolua_S, 4,&arg2, "BezierToForward:create");
        ok &= luaval_to_number(tolua_S, 5,&arg3, "BezierToForward:create");
        if(!ok)
        {
            tolua_error(tolua_S,"invalid arguments in function 'lua_custom_BezierToForward_create'", nullptr);
            return 0;
        }
        BezierToForward* ret = BezierToForward::create(arg0, arg1, arg2, arg3);
        object_to_luaval<BezierToForward>(tolua_S, "BezierToForward",(BezierToForward*)ret);
        return 1;
    }
    luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "BezierToForward:create",argc, 2);
    return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'lua_custom_BezierToForward_create'.",&tolua_err);
#endif
    return 0;
}



int tolua_cocos2d_utils_captureScreen(lua_State* tolua_S)
{
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!toluafix_isfunction(tolua_S,1,"LUA_FUNCTION",0,&tolua_err))
        goto tolua_lerror;
    else
#endif
    {
        LUA_FUNCTION handler = toluafix_ref_function(tolua_S,1,0);
        Utils::captureScreen([=](bool succeed, Texture2D* texture ){
            tolua_pushboolean(tolua_S, succeed);
            object_to_luaval<cocos2d::Texture2D>(tolua_S,"cc.Texture2D",texture);
            LuaEngine::getInstance()->getLuaStack()->executeFunctionByHandler(handler, 2);
            LuaEngine::getInstance()->removeScriptHandler(handler);
        });
        
        return 0;
    }
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'tolua_cocos2d_utils_captureScreen'.",&tolua_err);
    return 0;
#endif
}

int tolua_cocos2d_utils_toluafixRemoveFunctionByRefid(lua_State* tolua_S)
{
    LUA_FUNCTION handler = (int) tolua_tonumber(tolua_S, 1, 0);
    LuaEngine::getInstance()->removeScriptHandler(handler);
    return 0;
}

static void extendBezierByForward(lua_State* tolua_S)
{
    lua_pushstring(tolua_S,"BezierByForward");
    lua_rawget(tolua_S,LUA_REGISTRYINDEX);
    if (lua_istable(tolua_S,-1))
    {
        lua_pushstring(tolua_S,"create");
        lua_pushcfunction(tolua_S,lua_custom_BezierByForward_create);
        lua_rawset(tolua_S,-3);
    }
    lua_pop(tolua_S, 1);
}

static void extendBezierToForward(lua_State* tolua_S)
{
    lua_pushstring(tolua_S,"BezierToForward");
    lua_rawget(tolua_S,LUA_REGISTRYINDEX);
    if (lua_istable(tolua_S,-1))
    {
        lua_pushstring(tolua_S,"create");
        lua_pushcfunction(tolua_S,lua_custom_BezierToForward_create);
        lua_rawset(tolua_S,-3);
    }
    lua_pop(tolua_S, 1);
}



static int tolua_cocos2dx_Configuration_getInstance(lua_State* tolua_S)
{
    Configuration* tolua_ret = (Configuration*)  Configuration::getInstance();
    tolua_pushusertype(tolua_S,(void*)tolua_ret,"Configuration");
    return 1;
}

static int tolua_cocos2dx_Configuration_getValue(lua_State* L)
{
    int argc = 0;
    cocos2d::Configuration* cobj = nullptr;

    cobj = (cocos2d::Configuration*)tolua_tousertype(L,1,0);
    argc = lua_gettop(L)-1;
    if (argc == 1)
    {
        std::string arg1;
        luaval_to_std_string(L, 2, &arg1);
        const Value& value = cobj->getValue(arg1);
        if(value.isNull()){
            return 0;
        }
        ccvalue_to_luaval(L,value);
        return 1;
    }
    luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Configuration:getValue",argc, 1);
    return 0;
}

static int tolua_cocos2dx_Configuration_setValue(lua_State* L)
{
    int argc = 0;
    cocos2d::Configuration* cobj = nullptr;
    
    cobj = (cocos2d::Configuration*)tolua_tousertype(L,1,0);
    argc = lua_gettop(L)-1;
    if (argc == 2)
    {
        std::string arg1;
        std::string arg2;
        luaval_to_std_string(L, 2, &arg1);
        luaval_to_std_string(L, 3, &arg2);
        cobj->setValue(arg1, Value(arg2));
        return 0;
    }
    luaL_error(L, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Configuration:setValue", argc, 1);
    return 0;
}

/* Open function */
static void register_cocos2dx_extra(lua_State* L)
{
    tolua_open(L);
    tolua_usertype(L,"cc.Ref");
    tolua_usertype(L,"Configuration");

    tolua_module(L,"cc",0);
    tolua_beginmodule(L,"cc");
        tolua_cclass(L,"Configuration","Configuration","cc.Ref",NULL);
        tolua_beginmodule(L,"Configuration");
            tolua_function(L,"getInstance",tolua_cocos2dx_Configuration_getInstance);
            tolua_function(L,"getValue",tolua_cocos2dx_Configuration_getValue);
            tolua_function(L,"setValue",tolua_cocos2dx_Configuration_setValue);
        tolua_endmodule(L);

    tolua_endmodule(L);
}


static int lua_custom_PickerView_addEventListener(lua_State* L)
{
    if (nullptr == L)
        return 0;
    
    int argc = 0;
    cocos2d::ui::PickerView* self = nullptr;
    
#if COCOS2D_DEBUG >= 1
    tolua_Error tolua_err;
    if (!tolua_isusertype(L,1,"ccui.PickerView",0,&tolua_err)) goto tolua_lerror;
#endif
    
    self = static_cast<cocos2d::ui::PickerView*>(tolua_tousertype(L,1,0));
    
#if COCOS2D_DEBUG >= 1
    if (nullptr == self) {
        tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_ListView_addEventListener'\n", NULL);
        return 0;
    }
#endif
    argc = lua_gettop(L) - 1;
    if (1 == argc)
    {
#if COCOS2D_DEBUG >= 1
        if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
        {
            goto tolua_lerror;
        }
#endif
        LUA_FUNCTION handler = (  toluafix_ref_function(L,2,0));
        
        auto pickerViewCallback = [=](cocos2d::Ref* ref,cocos2d::ui::PickerView::EventType eventType,int idx){
            LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
            stack->pushObject(ref, "cc.Ref");
            stack->pushInt((int)eventType);
            stack->pushInt(idx);
            stack->executeFunctionByHandler(handler, 3);
            stack->clean();
        };
        self->addEventListener((cocos2d::ui::PickerView::ccPickerViewCallback)pickerViewCallback);
        
        ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
        return 0;
    }
    
    luaL_error(L, "'addEventListener' function of PickerView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
    
    return 0;
    
#if COCOS2D_DEBUG >= 1
tolua_lerror:
    tolua_error(L,"#ferror in function 'addEventListener'.",&tolua_err);
    return 0;
#endif
}

static void extendPickerView(lua_State* L)
{
    lua_pushstring(L, "ccui.PickerView");
    lua_rawget(L, LUA_REGISTRYINDEX);
    if (lua_istable(L,-1))
    {
        tolua_function(L, "addEventListener", lua_custom_PickerView_addEventListener);
    }
    lua_pop(L, 1);
}


static int luaExtend_custom_ShaderNode_setBlendFunc(lua_State* tolua_S)
{
    int argc = 0;
    ShaderNode* self = nullptr;

    self = static_cast<ShaderNode*>(tolua_tousertype(tolua_S,1,0));
    
    argc = lua_gettop(tolua_S) - 1;
    if (2 == argc)
    {
        GLenum src, dst;
        if (!luaval_to_int32(tolua_S, 2, (int32_t*)&src, "ShaderNode:setBlendFunc"))
            return 0;
        
        if (!luaval_to_int32(tolua_S, 3, (int32_t*)&dst, "ShaderNode:setBlendFunc"))
            return 0;
        
        BlendFunc blendFunc = {src, dst};
        self->setBlendFunc(blendFunc);
        return 0;
    }
    
    
    luaL_error(tolua_S, "'setBlendFunc' has wrong number of arguments: %d, was expecting %d\n", argc, 2);
    return 0;
}

static void extendShaderNode(lua_State* L)
{
    lua_pushstring(L,"ShaderNode");
    lua_rawget(L,LUA_REGISTRYINDEX);
    if (lua_istable(L,-1))
    {
        lua_pushstring(L,"setBlendFunc");
        lua_pushcfunction(L,luaExtend_custom_ShaderNode_setBlendFunc);
        lua_rawset(L,-3);
    }
    lua_pop(L, 1);
}


static int luaExtend_custom_BlurBackgroudNode_setEventCallback(lua_State* L)
{
    if (nullptr == L)
        return 0;
    
    int argc = 0;
    BlurBackgroudNode* self = nullptr;
    
    self = static_cast<BlurBackgroudNode*>(tolua_tousertype(L,1,0));
    
    argc = lua_gettop(L) - 1;
    if (1 == argc)
    {
        LUA_FUNCTION handler = (  toluafix_ref_function(L,2,0));
        
        auto callback = [=](bool befor){
            LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
            stack->pushBoolean(befor);
            stack->executeFunctionByHandler(handler, 1);
            stack->clean();
        };
        self->setEventCallback(callback);
        
        ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
        return 0;
    }
    
    luaL_error(L, "'setEventCallback' function of BlurBackgroudNode has wrong number of arguments: %d, was expecting %d\n", argc, 1);
    
    return 0;
    
}

static void extendBlurBackgroudNode(lua_State* L)
{
    lua_pushstring(L,"BlurBackgroudNode");
    lua_rawget(L,LUA_REGISTRYINDEX);
    if (lua_istable(L,-1))
    {
        lua_pushstring(L,"setEventCallback");
        lua_pushcfunction(L,luaExtend_custom_BlurBackgroudNode_setEventCallback);
        lua_rawset(L,-3);
    }
    lua_pop(L, 1);
}


int register_all_custom_manual(lua_State* L)
{
    tolua_open(L);
    tolua_module(L, "custom", 0);
    tolua_beginmodule(L, "custom");
        tolua_function(L, "captureScreen", tolua_cocos2d_utils_captureScreen);
        tolua_function(L, "toluafixRemoveFunctionByRefid", tolua_cocos2d_utils_toluafixRemoveFunctionByRefid);
    tolua_endmodule(L);
    
    extendPickerView(L);
    
    extendBezierByForward(L);
    extendBezierToForward(L);
    extendShaderNode(L);
    extendBlurBackgroudNode(L);
    
    register_cocos2dx_extra(L);
    return 0;
}
